package com.demo.gulimall.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.demo.gulimall.product.config.MyThreadConfig;
import com.demo.gulimall.product.entity.*;
import com.demo.gulimall.product.mapper.SkuInfoMapper;
import com.demo.gulimall.product.service.*;
import com.demo.gulimall.product.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import java.util.List;
import java.util.concurrent.*;

/**
 * sku信息
 *
 * @author Chen Yuan
 */
@Slf4j
@Service
public class SkuInfoServiceImpl extends ServiceImpl<SkuInfoMapper, SkuInfo> implements SkuInfoService {

    @Autowired
    private SkuInfoMapper skuInfoMapper;

    @Autowired
    private SkuImagesService skuImagesService;

    @Autowired
    private SpuInfoDescService spuInfoDescService;

    @Autowired
    private AttrGroupService attrGroupService;

    @Autowired
    private SkuSaleAttrValueService skuSaleAttrValueService;

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;


    @Override
    public List<SkuInfo> getSkusBySpuId(Long spuId) {
        QueryWrapper<SkuInfo> skuQW = new QueryWrapper<>();
        skuQW.eq("spu_id", spuId);
        return this.list(skuQW);
    }


    @Override
    public SkuItemVo getSkuItem(Long skuId){
        SkuItemVo skuItem = new SkuItemVo();

        /*
        // 1. SKU 基本信息
        SkuInfo skuInfo = this.getById(skuId);
        skuItem.setSkuInfo(skuInfo);
        Long spuId = skuInfo.getSpuId();

        // 2. SKU 图片信息
        List<SkuImages> skuImages = skuImagesService.getImagesBySkuId(skuId);
        skuItem.setSkuImages(skuImages);

        // 3. 当前 SPU 销售属性组合
        List<ItemSaleAttrVo> saleAttrVos = skuSaleAttrValueService.selectSaleAttrsBySpuId(spuId);
        skuItem.setSaleAttrs(saleAttrVos);

        // 4. SPU 介绍
        SpuInfoDesc spuDesc = spuInfoDescService.getById(spuId);
        skuItem.setSpuInfoDesc(spuDesc);

        // 5. SPU 的规格参数信息
        Long catalogId = skuInfo.getCatalogId(); // 获取三级分类ID
        List<ItemSpuAttrGroupVo> attrGroups = attrGroupService.getAttrGroupWithAttrBySpuId(spuId, catalogId);
        skuItem.setAttrGroups(attrGroups);
         */

        // 使用 异步任务 进行改造
        // 给 1. 开启异步任务, 因为 3.\4.\5. 都需要 1. 的返回值, 所以使用 supplyAsync
        CompletableFuture<SkuInfo> skuInfoFuture = CompletableFuture.supplyAsync(() -> {
            // 1. SKU 基本信息
            SkuInfo skuInfo = this.getById(skuId);
            skuItem.setSkuInfo(skuInfo);
            return skuInfo;
        }, threadPoolExecutor);

        // 2. 和 1. 没有任何关联, 开启一个新的异步任务, 因为 2. 不需要返回值, 所以使用 runAsync
        CompletableFuture<Void> skuImageFuture = CompletableFuture.runAsync(() -> {
            // 2. SKU 图片信息
            List<SkuImages> skuImages = skuImagesService.getImagesBySkuId(skuId);
            skuItem.setSkuImages(skuImages);
        }, threadPoolExecutor);


        // 因为 3. 需要 1. 的结果, 所以需要接在 skuInfoFuture 后
        CompletableFuture<Void> saleAttrFuture = skuInfoFuture.thenAcceptAsync((skuInfo) -> {
            // 3. 当前 SPU 销售属性组合
            List<ItemSaleAttrVo> saleAttrVos = skuSaleAttrValueService.selectSaleAttrsBySpuId(skuInfo.getSpuId());
            skuItem.setSaleAttrs(saleAttrVos);
        }, threadPoolExecutor);

        // 4. 也是需要接在 1. 后的, 但是和 3. 是平级的, 所以还是跟在 skuInfoFuture 后面执行
        CompletableFuture<Void> spuDescFuture = skuInfoFuture.thenAcceptAsync((skuInfo) -> {
            // 4. SPU 介绍
            SpuInfoDesc spuDesc = spuInfoDescService.getById(skuInfo.getSpuId());
            skuItem.setSpuInfoDesc(spuDesc);
        }, threadPoolExecutor);

        // 5. 同 4. 接在 skuInfoFuture 后面执行
        CompletableFuture<Void> attrGroupFuture = skuInfoFuture.thenAcceptAsync((skuInfo) -> {
            // 5. SPU 的规格参数信息
            List<ItemSpuAttrGroupVo> attrGroups = attrGroupService.getAttrGroupWithAttrBySpuId(skuInfo.getSpuId(), skuInfo.getCatalogId());
            skuItem.setAttrGroups(attrGroups);
        }, threadPoolExecutor);

        // 等待所有任务都执行完成, 才返回结果
        try {
            CompletableFuture.allOf(skuInfoFuture, skuImageFuture, saleAttrFuture, spuDescFuture, attrGroupFuture).get();
        } catch (Exception e) {
            log.error("--> getSkuItem - 异步获取 sku 信息异常");
        }

        return skuItem;
    }
}
